#include "Regex.hpp"

using namespace std;



RegularExpressions::Regex::Regex(const char* regex, int flags) throw(ArgumentException)
{
	int ret = regcomp(&_preg, regex, flags);
	
	if(ret != 0)
	{
		char errbuff[256] = {0};
		regerror(ret, &_preg, errbuff, 256);
		throw ArgumentException(errbuff);
	}
}



RegularExpressions::Regex::Regex(const string& regex, int flags) throw(ArgumentException)
{
	int ret = regcomp(&_preg, regex.c_str(), flags);
	
	if(ret != 0)
	{
		char errbuff[256] = {0};
		regerror(ret, &_preg, errbuff, 256);
		throw ArgumentException(errbuff);
	}
}



RegularExpressions::Regex::~Regex()
{
	regfree(&_preg);
}



bool RegularExpressions::Regex::isMatch(const char* str, int flags) const
{
	if(regexec(&_preg, str, 1, NULL, flags) == 0)
		return true;
	
	return false;
}



bool RegularExpressions::Regex::isMatch(const string& str, int flags) const
{
	if(regexec(&_preg, str.c_str(), 0, NULL, flags) == 0)
		return true;
	
	return false;
}



RegularExpressions::Match RegularExpressions::Regex::match(const char* str, int flags) const
{
	regmatch_t* pmatch = new regmatch_t[_preg.re_nsub+1];
	
	if(regexec(&_preg, str, _preg.re_nsub+1, pmatch, flags) == 0)
	{
		unsigned int nbGroups;
		
		for(nbGroups=0 ; nbGroups<(_preg.re_nsub+1) && pmatch[nbGroups].rm_so != -1 ; ++nbGroups);
		
		RegularExpressions::Match m(static_cast<int>(nbGroups));
		
		for(unsigned int i=0 ; i<nbGroups ; ++i)
			m._groups[i] = Group(pmatch[i].rm_so, pmatch[i].rm_eo, 
								string(str+pmatch[i].rm_so, pmatch[i].rm_eo-pmatch[i].rm_so));
		
		delete[] pmatch;
		return m;
	}
	
	delete[] pmatch;
	return RegularExpressions::Match(0);
}



RegularExpressions::Match RegularExpressions::Regex::match(const string& str, int flags) const
{
	return match(str.c_str(), flags);
}



string RegularExpressions::Regex::replace(const string& str, const string& replace, int flags) const
{
	string copy(str);
	regmatch_t pmatch;
	unsigned int index = 0;
	
	while(index < copy.size() 
			&& regexec(&_preg, str.c_str()+index, 1, &pmatch, flags) == 0 
			&& pmatch.rm_so != -1)
	{
		copy.replace(index+pmatch.rm_so, pmatch.rm_eo-pmatch.rm_so, replace);
		index += pmatch.rm_so + replace.size();
	}
	
	return copy;
}



